﻿using System;
using System.Security.Cryptography;
using System.Text;

namespace Best.SmartCms.Utility
{
    public class AesUtility
    {
        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="text">要解密字符串</param>
        /// <param name="key"></param>
        /// <returns>返回解密后字符串</returns>
        public static String Decrypt(String text, String key)
        {
            AesCryptoServiceProvider asc = new AesCryptoServiceProvider();
            int len = text.Length / 2;
            byte[] inputByteArray = new byte[len];
            for (int x = 0; x < len; x++)
            {
                int i = Convert.ToInt32(text.Substring(x * 2, 2), 16);
                inputByteArray[x] = (byte)i;
            }
            asc.Key = GetDesKeyOrIv(key, 32);
            asc.IV = GetDesKeyOrIv(key, 16);

            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms, asc.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            return Encoding.Default.GetString(ms.ToArray());
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="text"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Encrypt(string text, string key)
        {
            AesCryptoServiceProvider asc = new AesCryptoServiceProvider();

            byte[] inputByteArray = Encoding.Default.GetBytes(text);
            asc.Key = GetDesKeyOrIv(key, 32);
            asc.IV = GetDesKeyOrIv(key, 16);

            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms, asc.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            StringBuilder returnValue = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                returnValue.AppendFormat("{0:X2}", b);
            }
            return returnValue.ToString();
        }

        private static byte[] GetDesKeyOrIv(string key, int length)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new Exception("key is null or empty");
            }

            string keyHash = Md5Hash(key);
            if (string.IsNullOrEmpty(keyHash))
                throw new Exception("key hash is null or empty");
            keyHash = keyHash.Substring(0, length);
            return Encoding.ASCII.GetBytes(keyHash);
        }

        private static string Md5Hash(string input)
        {
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }

        public static string StringToMd5Hash(string inputString)
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                var inputByteArray = Encoding.UTF8.GetBytes(inputString);
                var targetData = md5.ComputeHash(inputByteArray);
                var sb = new StringBuilder();
                for (int i = 0; i < targetData.Length; i++)
                {
                    sb.AppendFormat("{0:x2}", targetData[i]);
                }
                return sb.ToString();
            }
        }

    }
}
